﻿using System.Collections;
using System.Collections.Generic;

namespace Workstation
{
    public class BidirectionalDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>> where TKey : notnull where TValue : notnull
    {
        /// <summary>
        /// 正向字典
        /// </summary>
        private readonly Dictionary<TKey, TValue> _forwardDictionary;
        /// <summary>
        /// 反向字典
        /// </summary>
        private readonly Dictionary<TValue, TKey> _reverseDictionary;

        public BidirectionalDictionary()
        {
            _forwardDictionary = new Dictionary<TKey, TValue>();
            _reverseDictionary = new Dictionary<TValue, TKey>();
        }
        /// <summary>
        /// 尝试往双向字典新增
        /// </summary>
        /// <param name="key"><see cref="TKey"/></param>
        /// <param name="value">q<see cref="TValue"/></param>
        /// <returns></returns>
        public bool TryAdd(TKey key, TValue value)
        {
            if (!_forwardDictionary.ContainsKey(key) && !_reverseDictionary.ContainsKey(value))
            {
                _forwardDictionary.Add(key, value);
                _reverseDictionary.Add(value, key);
                return true;
            }
            return false;
        }
        /// <summary>
        /// 尝试更新或添加到双向字典
        /// </summary>
        /// <param name="key"><see cref="TKey"/></param>
        /// <param name="value">q<see cref="TValue"/></param>
        /// <returns></returns>
        public bool TryAddOrUpdate(TKey key, TValue value)
        {
            if (_forwardDictionary.ContainsKey(key))
            {
                _forwardDictionary[key] = value;
                _reverseDictionary[value] = key;
                return true;
            }
            else if (_reverseDictionary.ContainsKey(value))
            {
                TKey existingKey = _reverseDictionary[value];
                _forwardDictionary[existingKey] = value;
                return true;
            }
            else
            {
                _forwardDictionary.Add(key, value);
                _reverseDictionary.Add(value, key);
                return true;
            }
        }

        /// <summary>
        /// 根据 <see cref="TKey"/> 从双向字典移除
        /// </summary>
        /// <param name="key"><see cref="TKey"/></param>
        /// <returns></returns>
        public bool TryRemove(TKey key)
        {
            if (_forwardDictionary.TryGetValue(key, out var value))
            {
                if (_forwardDictionary.ContainsKey(key))
                {
                    _forwardDictionary.Remove(key);
                }
                _reverseDictionary.Remove(value);
                return true;
            }
            return false;
        }   
        
        /// <summary>
        /// 根据<see cref="TValue"/> 从双向字典移除
        /// </summary>
        /// <param name="value">q<see cref="TValue"/></param>
        /// <returns></returns>
        public bool TryRemove(TValue value)
        {
            if (_reverseDictionary.TryGetValue(value, out var key))
            {
                if (_forwardDictionary.ContainsKey(key))
                {
                    _forwardDictionary.Remove(key);
                }
                _reverseDictionary.Remove(value);
                return true;
            }
            return false;
        }

        public bool ContainsKey(TKey key)
        {
            return _forwardDictionary.ContainsKey(key);
        }

        public bool ContainsValue(TValue value)
        {
            return _reverseDictionary.ContainsKey(value);
        }

        public TKey GetKey(TValue value)
        {
            return _reverseDictionary[value];
        }

        public TValue GetValue(TKey key)
        {
            return _forwardDictionary[key];
        }
        /// <summary>
        /// 根据<see cref="TKey"/> 枚举 <see cref="TValue"/>
        /// </summary>
        /// <returns></returns>
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return _forwardDictionary.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
        /// <summary>
        /// 根据<see cref="TValue"/> 枚举 <see cref="TKey"/>
        /// </summary>
        /// <returns></returns>
        public IEnumerable<TValue> GetValues()
        {
            return _reverseDictionary.Keys;
        }
    }
}